#ifndef _CRSSOCKET

#define _CRSSOCKET


#include <winsock2.h>
#include <map>
#include "CCircleQueueBuff.h"

using namespace std;

class CClinetRC;

typedef map<SOCKET, CClinetRC*> ClientRC_MAP_TYPE;

//Socket 2.2, AF_INET, SOCK_STREAM, IPPROTO_TCP
class CRServerSocket
{
protected:
	int m_nOpenPort;	//Open for connecting port.
	int m_nMaxClient;	//Max client number.
	SOCKET m_hSSocket;	//Server socket handle.
	
	void (*m_AfterRunFunc)(CRServerSocket *pCRSS);		//callback function,it will be call after 'Run()'.
	void (*m_AfterConnectFunc)(CClinetRC *pCCRC);		//callback function,it will be call after client socket connected.
	void (*m_AfterDisconnectFunc)(CClinetRC *pCCRC);	//callback function,it will be call after client socket disconnected.
	void (*m_AfterRecvFunc)(CClinetRC *pCCRC);	//callback function,it will be call after client socket recv.
public:
	ClientRC_MAP_TYPE m_mapClientRC;	//connected (SOCKET, CClinetRC) mapping

	CRServerSocket();
	~CRServerSocket();
	//** Create Server Socket**
	enum _CreateServer_RET_ {
		CREATE_SUCCESS = 0,
		ALREADY_CREATE = -1,
		INIT_SOCKET_ERROR = -2,
		BINDING_ERROR = -3,
		SET_LISTEN_ERROR = -4,
	};
	int CreateServer(int nPort, int nMaxClient);

	//** Process Clinet Connect, Recv**
	int Run();

	//**Set Callback**
	void SetAfterRun(void (*AfterRunFunc)(CRServerSocket *pCRSS));
	void SetAfterConnect(void (*AfterConnectFunc)(CClinetRC *pCCRC));
	void SetAfterDisconnect(void (*AfterDisconnectFunc)(CClinetRC *pCCRC));
	void SetAfterRecv(void (*AfterRecvFunc)(CClinetRC *pCCRC));
};

// Client resource
#define DEFAULT_RCEV_BUF_SIZE 1024
class CClinetRC 
{
public:
	SOCKET m_hCSoket;	//Client scoket handle.
	sockaddr_in m_ClientInfo;
	CCircleQueueBuff *m_pcClientRecvBuf; //Client socket recv buffer.
	CClinetRC(SOCKET nCSocket, sockaddr_in ClientInfo, int RecvBufSize) {
		m_hCSoket = nCSocket;
		m_ClientInfo = ClientInfo;
		m_pcClientRecvBuf = new CCircleQueueBuff(RecvBufSize);
	};
	~CClinetRC() {
		if(m_pcClientRecvBuf) {
			delete m_pcClientRecvBuf;
			m_pcClientRecvBuf = NULL;
		}
	};
};

#endif _CRSSOCKET	//#ifndef _CRSSOCKET